package com.hujing.springsource.a05;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

public class ComponentScanPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        try {
            //查找Config类上是否有componentScan注解
            ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
            if (componentScan != null) {
                String[] packages = componentScan.basePackages();
                for (String p : packages) {
                    //需要将com.example.springsource.com.hujing.A05.component变成classpath*:com/example/springsource/com/hujing/A05/component/**/*.class
                    String path = "classpath*:" + p.replace(".", "/") + "/**/*.class";
//                    System.out.println(path);
                    CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
                    //根据路径获取资源
                    Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
                    for (Resource r : resources) {
//                        System.out.println(r.getFilename());
                        //判断这些类上是否加了@Component注解
                        MetadataReader reader = cachingMetadataReaderFactory.getMetadataReader(r);
                        //定义一个bean名字的生成器
                        AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
                        //查询元数据上是否有@Component或@Component的派生注解,如果有，就注册该bean
                        if (reader.getAnnotationMetadata().hasAnnotation(Component.class.getName())
                                || reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName())) {
//                            System.out.println("类名:" + reader.getClassMetadata().getClassName());
                            //获取bean的定义
                            AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(reader.getClassMetadata().getClassName()).getBeanDefinition();
                            if (configurableListableBeanFactory instanceof DefaultListableBeanFactory) {
                                DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
                                //生成bean的名字
                                String name = generator.generateBeanName(bd, beanFactory);
                                //将bean注册到bean工厂中
                                beanFactory.registerBeanDefinition(name, bd);
                            }

                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
